import storageUtils from '@/utils/common/storage.js'
import objUtils from '@/utils/common/obj.js'
import stringUtils from '@/utils/common/string.js'
import err from '@/utils/common/error.js'
import Judge from '../judge/judge.js'

// 利用storage实现的简易数据库

// 数据库集合(表)的引用对象
class StorageCollection {
  constructor (name, keys) {
    this.name = name
    // 过滤获得有关键值集，并建立对应的缓存
    this.keys = keys.filter((key) => {
      return key.indexOf(this.name) >= 0
    })
    // 数据缓存
    this.cache = {}
    // 初始化过滤条件
    this.initFilter()
  }
  
  // 初始化过滤条件
  initFilter () {
    this.filter = {
      // 指定全部内容
      all: true
    }
  }
  
  // 根据key名获取id
  getIdByKey (key) {
    const keyArr = key.split('-')
    return keyArr[keyArr.length - 1]
  }
  
  // 根据id获取key
  getKeyById (id) {
    return this.name + '-' + id
  }
  
  // 添加过滤条件，用_id获取对象
  // 每一个键值的命名格式均为 collectionName-_id,因此_id暴露在键名中，可以直接作为查询条件
  id (id) {
    this.filter.id = id
    this.filter.all = false
    return this
  }
  
  /* 
    添加过滤条件，暂时只支持
    {  
      a: 1,
      b: 2
    }
    代表a == 1 and b == 2
  */
  where (where = {}) {
    this.filter.where = where
    this.filter.all = false
    return this
  }
  
  // 添加一条字段
  async add (data = {}) {
    // id的格式默认为 时间戳+8位随即串
    const id = new Date().getTime() + stringUtils.randomStr()
    const key = this.name + '-' + id
    data._id = id
    // 存入storage
    await storageUtils.set(key, data)
    // 修改键值集和缓存
    this.keys.push(key)
    this.cache[id] = data
  }
  
  // 修改字段
  async update (data) {
    let result = {
      // 修改条数
      num: 0
    }
    
    // 修改一条
    const updateOneFromStorage = async (id, data) => {
      let updateData = objUtils.jsonClone(data)
      updateData._id = id
      const key = this.getKeyById(id)
      await storageUtils.set(key, updateData)
      result.num++
      // 修改缓存内容
      this.cache[id] = updateData
    }
    
    // 全部修改
    if (this.filter.all) {
      let executeList = []
      const len = this.keys.length
      for (let i = 0; i < len; i++) {
        const key = this.keys[i]
        const id = this.getIdByKey(key)
        executeList.push(updateOneFromStorage(id, data))
      }
      await Promise.all(executeList)
      
      // 还原过滤条件
      this.initFilter()
      return result
    }
    
    // 根据_id实现精准修改
    if (this.filter.id) {
      await updateOneFromStorage(this.filter.id, data)
      
      // 还原过滤条件
      this.initFilter()
      return result
    }
    
    // 其他情况 过滤条件控制修改
    // get方法已经获取到待删除的集合，同时也还原了过滤条件
    const dataResult = await this.get()
    let executeList = []
    const len = dataResult.length
    for (let i = 0; i < len; i++) {
      const obj = dataResult[i]
      const id = obj._id
      executeList.push(updateOneFromStorage(id, data))
    }
    await Promise.all(executeList)
    return result
  }
  
  // 删除字段
  async remove () {
    let result = {
      // 删除条数
      num: 0
    }
    
    // 删除一条
    const removeOneFromStorage = async (id, clearCache = true, clearKey = true) => {
      const key = this.getKeyById(id)
      await storageUtils.remove(key)
      result.num++
      // 删除缓存
      if (clearCache) {
        delete this.cache[id]
      }
      // 删除对应key
      if (clearKey) {
        const index = this.keys.indexOf(key)
        this.keys.splice(index, 1)
      }
    }
    
    // 清空集合
    if (this.filter.all) {
      let executeList = []
      const len = this.keys.length
      for (let i = 0; i < len; i++) {
        const key = this.keys[i]
        const id = this.getIdByKey(key)
        executeList.push(removeOneFromStorage(id, false, false))
      }
      await Promise.all(executeList)
      // 删除函数中clearCache设置为false,所以在这里统一清空缓存
      this.cache = {}
      // 删除函数中clearKey设置为false,所以在这里统一清空键值
      this.keys = []
      
      // 还原过滤条件
      this.initFilter()
      return result
    }
    
    // 根据_id实现精准删除
    if (this.filter.id) {
      await removeOneFromStorage(this.filter.id)
      
      // 还原过滤条件
      this.initFilter()
      return result
    }
    
    // 其他情况 过滤条件控制删除
    // get方法已经获取到待删除的集合，同时也还原了过滤条件
    const dataResult = await this.get()
    let executeList = []
    const len = dataResult.length
    for (let i = 0; i < len; i++) {
      const obj = dataResult[i]
      const id = obj._id
      executeList.push(removeOneFromStorage(id))
    }
    await Promise.all(executeList)
    return result
  }
  
  // 根据过滤条件，获取对象
  async get () {
    let signals = {
      // 是否过滤
      filter: false,
      // 是否切割
      limit: false,
      // 是否排序
      sort: false
    }
    let result
    
    // 获取集合的所有数据为第一优先级
    if (!signals.filter && this.filter.all) {
      result = await this.getAll()
      signals.filter = true
    }
    
    // 用id精确过滤为第一优先级，直接id对应的数据，其他过滤条件均无效
    if (!signals.filter && this.filter.id) {
      const res = await this.getById(this.filter.id)
      result = [res]
      signals.filter = true
      // 因为只有一条数据，所以也不需要进行排序和切割
      signals.limit = true
      signals.sort = true
    }
    
    // where进行具体字段的过滤为第二优先级
    if (!signals.filter && this.filter.where) {
      result = await this.getWhere()
      signals.filter = true
    }
    
    // 对获取到的字段进行排序
    if (!signals.sort && this.filter.sort) {
    }
    
    // 对排序后的结果进行切割
    if (!signals.limit && this.filter.limit) {
    }
    
    // 目标确定后，还原过滤条件
    this.initFilter()
    
    return result
  }
  
  // 获取所有数据
  async getAll () {
    if (Object.keys(this.cache).length === this.keys.length) {
      // 拷贝返回，避免缓存被折腾
      return objUtils.jsonClone(Object.values(this.cache))
    }
    
    let executeList = []
    const len = this.keys.length
    for (let i = 0; i < len; i++) {
      const key = this.keys[i]
      const id = this.getIdByKey(key)
      executeList.push(this.getById(id))
    }
    
    return await Promise.all(executeList)
  }
  
  // 获取where条件下的数据
  async getWhere () {
    if (!objUtils.isObject(this.filter.where)) {
      return Promise.reject(err('STORAGE_REMOVE_FAILED'))
    }
    
    // 先获取所有数据，从中筛选
    const result = await this.getAll()
    
    return result.filter((obj) => {
      if (typeof obj !== 'object' || !obj) {
        return false
      }
      
      let sign = 1
      for (let key in this.filter.where) {
        const currentSign = this.filter.where[key] === obj[key]
        // 目前只支持and方法
        sign = sign & currentSign
      }
      return sign ? true : false
    })
  }
  
  // 根据指定_id获取数据
  async getById (id) {
    if (this.cache[id]) {
      return objUtils.jsonClone(this.cache[id])
    }
    
    let res = await storageUtils.get(this.getKeyById(id))
    // 保留关键字_id一定要有
    res._id = id
    this.cache[id] = res
    return objUtils.jsonClone(res)
  }
}

class StorageDB {
  // 单例类
  constructor () {
    if (typeof StorageDB.instance === 'object') {
      return StorageDB.instance
    }
    StorageDB.instance = this
    
    // 初始化存储中所有key
    this.keys = []
    // 初始化缓存
    this.cache = {}
    // 是否完成
    this.enabled = false
    
    return this
  }
  
  // 异步初始化
  async init () {
    if (!this.enabled) {
      const res = await storageUtils.info()
      this.currentSize = res.currentSize
      this.limitSize = res.limitSize
      this.keys = res.keys
      this.enabled = true
    }
    return this
  }
  
  // 数据库集合(表)的引用对象
  collection (name) {
    if (this.cache[name]) {
      return this.cache[name]
    }
    const collectionObj = new StorageCollection(name, this.keys)
    this.cache[name] = collectionObj
    return collectionObj
  }
}

export default StorageDB